#pragma once

#include <string>
#include <mutex>

using namespace std;

#ifndef WIN32
#   include <sys/stat.h>
#   include <sys/file.h>
#   include <sys/time.h>
#   include <unistd.h>
#endif

#ifdef ENABLE_USE_LOGCPLUS 
#include "logcplus/logcplus.h"
using namespace logcplus;
#endif 

#include "topcvt_cross_platform.hpp"

#define TOPCVT_DEBUG_LOG         "topcvt.log"
#define TOPCVT_DEUBG_ENV_TAG     "TOPCVT_LOGLEVEL"

namespace topcvt
{
    typedef enum
    {
        CVT_TRACE = 0,
        CVT_DEBUG,
        CVT_INFO,
        CVT_WARN,
        CVT_ERROR
    }eCVTLogLevel_t;

    char* topcvt_gettime(char* datetime);
    long  topcvt_getfilesize(const char* psFileName);
    long  topcvt_getfilesize(FILE* hFile);
    bool  topcvt_exists_file(const char* psFileName);

    class TOPCVT_API topcvt_log
    {
    private:
        FILE* m_fpDebug;
        char m_fLogName[100];
        eCVTLogLevel_t m_fLevel;
        int m_console;
        
        topcvt_log();
        topcvt_log(const topcvt_log& ) = default;

        void rotate();

        static topcvt_log* m_instance;
        static std::mutex m_lock;
        static bool m_status;

        class AutoRelease
        {
            public:
            ~AutoRelease()
            {
                if (topcvt_log::m_instance)
                {
                    std::lock_guard<std::mutex> _lock(topcvt_log::m_lock);
                    if (topcvt_log::m_instance)
                    {
	                    topcvt_log::m_instance->close();
	                    delete topcvt_log::m_instance;
	                    topcvt_log::m_instance = nullptr;
                    }
                }
            };
        };	    
        static AutoRelease m_release;
    public:
        int initlog(const char* logname);
        void setlevel(eCVTLogLevel_t level){ m_fLevel = level;};
        void setConsole(int on) { m_console = on;}
        int openlog();
        void close();
        void writelog(const char* file,const char* function,int line,int level,const char* fmt,...);
        void writelog(int dbsLevel,int level,const char* data);	
        static topcvt_log* rootLog();			
    };

#ifndef ENABLE_USE_LOGCPLUS  
    #define TRXLOG_HANDLE            topcvt_log::rootLog()
    #define TLOG_SETLEVEL(LEVEL) topcvt_log::rootLog()->setlevel((eCVTLogLevel_t)LEVEL)
    #define TLOG_LOGTYPE(LOGTYPE)    topcvt_log::rootLog()->setConsole(LOGTYPE-1)
    #define TLOG_INIT(LOGNAME)       topcvt_log::rootLog()->initlog(LOGNAME)
    #define TLOG_TRACE(fmt, ...)     topcvt_log::rootLog()->writelog(__FILE__, __FUNCTION__ , __LINE__,CVT_TRACE,fmt,##__VA_ARGS__)
    #define TLOG_DEBUG(fmt, ...)     topcvt_log::rootLog()->writelog(__FILE__, __FUNCTION__ , __LINE__,CVT_DEBUG,fmt,##__VA_ARGS__)
    #define TLOG_INFO( fmt, ...)     topcvt_log::rootLog()->writelog(__FILE__, __FUNCTION__ , __LINE__,CVT_INFO ,fmt,##__VA_ARGS__)
    #define TLOG_WARN( fmt, ...)     topcvt_log::rootLog()->writelog(__FILE__, __FUNCTION__ , __LINE__,CVT_WARN ,fmt,##__VA_ARGS__)
    #define TLOG_ERROR(fmt, ...)     topcvt_log::rootLog()->writelog(__FILE__, __FUNCTION__ , __LINE__,CVT_ERROR,fmt,##__VA_ARGS__)
#else
    #define TLOG_SETLEVEL LOGCPLUS_SETLEVEL  
#endif

}
